package com.tedu.element.bubble;

import com.tedu.element.Direction;
import com.tedu.element.ElementObj;
import com.tedu.element.map.GameMap;
import com.tedu.element.map.MapAware;
import com.tedu.element.map.MapObj;
import com.tedu.element.utils.GameUtils;
import com.tedu.manager.ElementManager;
import com.tedu.manager.GameElement;
import com.tedu.manager.GameLoad;
import com.tedu.show.GameConstants;

import java.awt.*;

/**
 * @说明 泡泡类 - 使用精灵图实现多帧动画
 */
public class Bubble extends ElementObj implements MapAware {
    // 精灵图相关常量
    private static final int SPRITE_WIDTH = GameConstants.BUBBLE_SPRITE_WIDTH;  // 精灵图中每个泡泡帧的宽度
    private static final int SPRITE_HEIGHT = GameConstants.BUBBLE_SPRITE_HEIGHT; // 精灵图中每个泡泡帧的高度
    private static final long EXPLOSION_DELAY = GameConstants.BUBBLE_EXPLOSION_DELAY; // 3秒后爆炸

    // 游戏中的泡泡大小
    private int bubbleSize = GameConstants.BUBBLE_SIZE;

    // 泡泡属性
    private int power = GameConstants.PLAYER_BOMB_POWER; // 爆炸威力(格子数)
    private long plantTime; // 泡泡放置时间
    private boolean exploding = false; // 是否正在爆炸
    private BubbleExplosionListener listener = null; // 回调接口

    // 动画相关属性
    private int frameX = 0; // 当前帧在精灵图中的X坐标
    private int frameY = 0; // 当前帧在精灵图中的Y坐标
    private long lastFrameTime;     // 上次帧切换时间
    private long animationStartTime; // 动画开始时间

    // 地图引用
    private GameMap gameMap;

    /**
     * 内部枚举，用于述爆炸水柱在延伸时遇到的情况
     */
    private enum ExplosionStopType {
        CONTINUE,           // 路径清晰，爆炸可以继续
        DESTROY_AND_STOP,   // 摧毁了一个障碍物，爆炸停止
        HARD_STOP           // 遇到了不可摧毁的墙壁，爆炸停止
    }

    public Bubble() {}

    // str = "gridX, gridY, power"
    @Override
    public ElementObj createElement(String str) {
        String[] split = str.split(",");
        // 设置泡泡网格坐标
        this.setGridX(Integer.parseInt(split[0]));
        this.setGridY(Integer.parseInt(split[1]));
        // 设置泡泡大小
        this.setW(bubbleSize);
        this.setH(bubbleSize);
        // 设置泡泡爆炸威力
        this.power = Integer.parseInt(split[2]);
        // 设置时间
        this.plantTime = System.currentTimeMillis();
        this.animationStartTime = plantTime;
        this.lastFrameTime = plantTime;
        // 设置泡泡精灵图
        this.setIcon(GameLoad.imgMap.get("bubble_sprite"));
        return this;
    }

    @Override
    public void setGameMap(GameMap gameMap) {
        this.gameMap = gameMap;
    }

    /**
     * 设置爆炸事件的监听器
     */
    public void setExplosionListener(BubbleExplosionListener listener) {
        this.listener = listener;
    }

    @Override
    public void showElement(Graphics g) {
        if (isLive()) {
            // 使用精灵图绘制泡泡
            g.drawImage(this.getIcon().getImage(),
                    getX(), getY(),
                    getX() + bubbleSize,
                    getY() + bubbleSize,
                    frameX, frameY,
                    frameX + SPRITE_WIDTH,
                    frameY + SPRITE_HEIGHT,
                    null);

            // 绘制倒计时文本（可选）
            long remaining = EXPLOSION_DELAY - (System.currentTimeMillis() - plantTime);
            if (remaining > 0) {
                g.setColor(Color.WHITE);
                g.setFont(new Font("Arial", Font.BOLD, 14));
                String timeText = String.valueOf((remaining / 1000) + 1);
                g.drawString(timeText, getX() + bubbleSize / 2 - 5, getY() + bubbleSize / 2 + 5);
            }

            if (GameConstants.DEBUG_MODE) {
                g.setColor(new Color(255, 0, 0, 100));
                Rectangle rect = getRectangle();
                g.fillRect(rect.x, rect.y, rect.width, rect.height);
            }
        }
    }

    @Override
    protected void updateImage(long time) {
        if (exploding) {
                this.setLive(false); // 爆炸结束，移除泡泡
        } else {
            // 更新泡泡动画帧
            long currentTime = System.currentTimeMillis();
            long elapsed = currentTime - animationStartTime;

            // 计算当前应该显示的帧
            int totalFrames = (int) (elapsed * GameConstants.BUBBLE_ANIMATION_SPEED / 1000) % GameConstants.BUBBLE_FRAME_COUNT;
            frameX = totalFrames * SPRITE_WIDTH;

            // 添加呼吸效果 - 随时间轻微缩放
            float scale = 1.0f + 0.03f * (float) Math.sin(elapsed / 200.0);
            this.bubbleSize = (int) (GameConstants.BUBBLE_SIZE * scale);
        }
    }

    @Override
    public void model(long gameTime) {
        // 检查泡泡是否该爆炸（3秒后）
        if (!exploding && System.currentTimeMillis() - plantTime > EXPLOSION_DELAY) {
            explode();
        }
        super.model(gameTime);
    }

    /**
     * 触发泡泡爆炸，可以是主动或连锁
     */
    public void explode() {
        if (exploding) {
            return;
        }
        exploding = true;
        // 通知放置者泡泡爆炸
        if (listener != null) {
            listener.onBubbleExploded(this);
        }
        // 创建中心爆炸效果
        createExplosion(
                getGridX(),
                getGridY(),
                Explosion.ExplosionType.CENTER
        );
        // 向四个方向创建水柱
        for (Direction dir : Direction.values()) {
            createDirectionalExplosions(dir);
        }
    }

    /**
     * 创建指定方向的连续爆炸效果
     * 此函数现在只负责传播逻辑，即按设定的 power 一格一格地延伸
     * 每一格具体会发生，交给 handleExplosionAt() 方法去处理和判断
     */
    private void createDirectionalExplosions(Direction dir) {
        for (int i = 1; i <= power; i++) {
            // 根据方向计算爆炸位置
            int currentGridX = getGridX() + dir.dx * i;
            int currentGridY = getGridY() + dir.dy * i;

            // 判断当前格子的情况并进行处理
            ExplosionStopType stopType = handleExplosionAt(currentGridX, currentGridY);

            // 如果当前格子是不可摧毁的墙，直接停止
            if (stopType == ExplosionStopType.HARD_STOP) {
                break;
            }
            // 如果当前格子是可摧毁的障碍物，则产生末端效果并停止
            if (stopType == ExplosionStopType.DESTROY_AND_STOP) {
                createExplosion(currentGridX, currentGridY, GameUtils.getEndType(dir));
                break;
            }

            // 如果当前格子是空地
            // 向前看一格，检查下一个格子是否被阻挡
            boolean nextTileIsBlocked = isTileBlocked(currentGridX + dir.dx, currentGridY + dir.dy);

            if (i == power || nextTileIsBlocked) {
                createExplosion(currentGridX, currentGridY, GameUtils.getEndType(dir));
                break;
            } else {
                createExplosion(currentGridX, currentGridY, GameUtils.getDirectionalType(dir));
            }
        }
    }

    /**
     * 处理指定网格坐标的爆炸交互
     * @return ExplosionStopType 指示爆炸应继续、停止还是摧毁后停止
     */
    private ExplosionStopType handleExplosionAt(int gridX, int gridY) {
        if (gameMap == null) {
            return ExplosionStopType.HARD_STOP;
        }
        MapObj tile = gameMap.getTile(gridX, gridY);
        // 情况1：是空地 -> 爆炸继续
        if (tile != null && tile.isWalkable()) {
            return ExplosionStopType.CONTINUE;
        }
        // 情况2：遇到地图边界或不可破坏的墙壁 -> 硬停止
        if (tile == null || tile.isInvincible()) {
            return ExplosionStopType.HARD_STOP;
        }
        // 情况3：遇到可破坏的障碍物 -> 销毁并停止
        return ExplosionStopType.DESTROY_AND_STOP;
    }

    /**
     * 仅用于检查指定格子是否被任何类型的障碍物阻挡
     * @return boolean true表示被阻挡，false表示为空地
     */
    private boolean isTileBlocked(int gridX, int gridY) {
        if (gameMap == null) {
            return true; // 视作被阻挡
        }
        MapObj tile = gameMap.getTile(gridX, gridY);
        // 被阻挡的情况：格子不存在，格子不可摧毁
        return tile == null || (tile.isInvincible() && !tile.isEmpty());
    }

    /**
     * 创建爆炸水柱
     * @param gridX 水柱网格X坐标
     * @param gridY 水柱网格Y坐标
     * @param type 水柱类型
     */
    private void createExplosion(int gridX, int gridY, Explosion.ExplosionType type) {
        ElementObj obj = GameLoad.getObj("explosion");
        assert obj != null;
        ElementObj element = obj.createElement(gridX + "," + gridY + "," + type);
        ElementManager.getManager().addElement(element, GameElement.EXPLOSION);
    }

    public boolean isExploding() {
        return exploding;
    }
}